package com.lucker.service.push.socket;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.lucker.common.model.EntityHeader;
import com.lucker.common.model.PushEntity;
import com.lucker.common.util.AESCBCUtil;
import com.lucker.common.util.AESUtil;
import com.lucker.common.util.CommonStr;
import com.lucker.service.push.web.CustomMessageHandle;

/***
 * 该推送服务，只能部署在单台服务器上面，如果后面是集群部署，则需要把这个服务，单独列出去部署在一台服务器上面。
 * @author zyf
 *
 */



@Service
public class SocketServiceImpl implements SocketService {
	Logger logger = LoggerFactory.getLogger(SocketServiceImpl.class);
	Socket socket = null;
	public void initSocketListener() {
		try {
			ServerSocket ss = new ServerSocket(9997);
			while(true) {
				socket = ss.accept();
				CustomMessageHandle handle = new CustomMessageHandle(socket);
				handle.start();
				logger.error("服务器端口开始监听...........................");
			}
		} catch (Exception e) {
			
		}
	}
	
	/***
	 * @param targetId 采种ID，如果不方便获取可以用 省ID+彩票大类ID，确定唯一
	 * @param message 向客户端推送的内容
	 * @throws Exception 异常
	 */
	public void pushMessage(String targetId,String message) throws Exception {
		if(targetId != null && targetId.length() > 0) {
			List<Socket> list = CustomMessageHandle.socketMap.get(targetId);
			
			if(CollectionUtils.isEmpty(list)) {
				logger.error(targetId + "该彩种没有客户端长链接保持, 不进行推送");
			}else {
				logger.error("本次推送彩种ID,{} ,待推送客户端数量{} , 发送内容: {}", targetId, (list == null ? 0 : list.size()) , message);
				for(int i = 0 ; list != null && i < list.size() ; i++) {
					Socket sock = list.get(i);
					if(sock != null) {
						sendMsg(targetId,sock,message);
						logger.error("socket推送成功消息:  " + message);
					}
				}
			}
		}
	}
	
	public void pushMessage(String targetId,PushEntity<?> pushEntity) throws Exception{
		if(targetId != null && targetId.length() > 0) {
			List<Socket> list = CustomMessageHandle.socketMap.get(targetId);
			
			if(CollectionUtils.isEmpty(list)) {
				logger.error(targetId + "该彩种没有客户端长链接保持, 不进行推送");
			}else {
				logger.error("本次推送彩种ID,{} ,待推送客户端数量{} , 发送内容: {}", targetId, (list == null ? 0 : list.size()) , JSONObject.toJSONString(pushEntity));
				for(int i = 0 ; list != null && i < list.size() ; i++) {
					Socket sock = list.get(i);
					if(sock != null) {
						sendMsg(targetId,sock,JSONObject.toJSONString(pushEntity));
						logger.error("socket推送成功消息:  " + JSONObject.toJSONString(pushEntity));
					}
				}
			}
		}
	}
	
	
	public void sendMsg(String targetId,Socket sock,String message) throws Exception {
		if(sock != null) {
			try {
				PrintWriter pw = new PrintWriter(sock.getOutputStream());
				pw.println(AESCBCUtil.encrypt(message));
				pw.flush();
			}catch(IOException e) {
				removeDisabledSocket(sock,targetId);
			}
		}
	}
	
	public void sendMsg(String targetId,Socket sock,@SuppressWarnings("rawtypes") PushEntity pushEntity) throws Exception {
		if(sock != null) {
			try {
				PrintWriter pw = new PrintWriter(sock.getOutputStream());
				pw.println(AESCBCUtil.encrypt(JSONObject.toJSONString(pushEntity)));
				pw.flush();
			}catch(IOException e) {
				removeDisabledSocket(sock,targetId);
			}
		}
	}
	
	/***
	 * 从服务端保存的客户端链接列表中删除当前下线的链接
	 * @param _sock 客户端长链接
	 * @param targetId 链接标识 ： 当前系统链接标识采用 彩票ID
	 *  
	 */
	public void removeDisabledSocket(Socket _sock,String targetId) {
		if(StringUtils.isNotBlank(targetId) && _sock != null) {
			List<Socket> list = CustomMessageHandle.socketMap.get(targetId);
			for(Socket s : list) {
				if(s == _sock) {
					list.remove(s);
					logger.error("长链接列表删除提醒 : " + targetId + " 这个彩票ID对应的SOCKET发送失败 客户端IP" + _sock.getRemoteSocketAddress().toString());
				}
			}
			CustomMessageHandle.socketMap.put(targetId, list);
		}		
	}
	/***
	 * 定时批量向客户端发送用于心跳检测的长链接保活消息。
	 * @throws Exception
	 */
	public void sendKeepalivedMessage() throws Exception{
		if(CustomMessageHandle.socketMap != null) {
			logger.error("当前系统有" + CustomMessageHandle.socketMap.size() + "个客户端正在链接当前服务器,");
		}
		PushEntity<String> entity = null;
		EntityHeader header = null;
		for(Map.Entry<String, List<Socket>> entry : CustomMessageHandle.socketMap.entrySet()) {
			String key = entry.getKey();
			List<Socket> list = entry.getValue();
			logger.info("开始给" + (list == null ?  0 : list.size()) + "个客户端推送信息,");
			for(Socket sock : list) {
				entity = new PushEntity<String>();
				entity.setData("loop");
				header = new EntityHeader(1);
				entity.setEntitiyHeader(header);
				sendMsg(key,sock,entity);
			}
			logger.info("给" + (list == null ?  0 : list.size()) +  "个客户端推送完成,");
		}
		
	}
}
